package com.stormrage.edu.serv.adm.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.shiro.authz.permission.WildcardPermission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.stormrage.constants.ErrCons;
import com.stormrage.edu.dao.adm.AdmAcctDao;
import com.stormrage.edu.serv.adm.AdmAcctResServ;
import com.stormrage.edu.serv.adm.AdmAcctServ;
import com.stormrage.edu.serv.adm.AdmResServ;
import com.stormrage.entity.adm.AdmAcct;
import com.stormrage.entity.adm.AdmAcctRes;
import com.stormrage.entity.adm.AdmRes;
import com.stormrage.entity.adm.rep.AdmAcctRep;
import com.stormrage.entity.adm.rep.AdmPermsRep;
import com.stormrage.entity.adm.rep.AdmResRep;
import com.stormrage.entity.adm.req.AdmAcctReq;
import com.stormragetech.core.exception.StormrageTechException;
import com.stormragetech.core.util.SecureUtil;

/**
 * @author www.stormragetech.com
 * @date 2016年1月19日
 * @version 1.0.0
 */
@Service
public class AdmAcctServImpl implements AdmAcctServ {

	private static final Logger logger = LoggerFactory.getLogger(AdmAcctServImpl.class);

	@Autowired
	private AdmAcctDao acctDao;

	@Autowired
	private AdmResServ resServ;

	@Autowired
	private AdmAcctResServ admAcctResServ;

	@Override
	public Integer create(final AdmAcctReq arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 Create 】-【 STARTED 】");

		logger.debug(" 添加管理员的req为 " + arg0.toString());

		// ------------------ 验证用户名是否重复 ------------------
		Boolean b = isExist(arg0.getAcct());
		if (b) {
			throw StormrageTechException.instance(ErrCons.SERV_ERR, "管理员用户名已存在", StormrageTechException.ERR_APP,
					"【AdmAcctServImpl】- 【 Create 】");
		}

		// ------------------ 创建管理员 ------------------
		AdmAcct acct = AdmAcct.instance(arg0.getAcct(), arg0.getPass(), arg0.getRole(), arg0.getRealName());
		Integer acctId = acctDao.create(acct);

		// ------------------ 创建管理员权限 ------------------
		if (null == arg0.getRole() || arg0.getRole().equals(1) && (null == arg0.getRes() || arg0.getRes().equals(""))) {
			throw StormrageTechException.instance(ErrCons.SERV_ERR, "管理员角色为空", StormrageTechException.ERR_APP,
					"【AdmAcctServImpl】- 【 Create 】");
		}
		for (String resId : arg0.getRes().split(",")) {
			AdmAcctRes acctRes = AdmAcctRes.instance(acctId, Integer.valueOf(resId));
			admAcctResServ.create(acctRes);
		}

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 Create 】-【 COMPLETED 】");
		return acctId;

	}

	@Override
	public void update(final AdmAcct arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 update 】-【 STARTED 】");

		// ------------------ 获取管理员详细信息 ------------------
		AdmAcct acct = queryById(arg0.getId());
		if (null == acct) {
			throw StormrageTechException.instance(ErrCons.SERV_ERR, "管理员为空", StormrageTechException.ERR_APP,
					"【AdmAcctServImpl】- 【 UpdatePass 】");
		}

		// ------------------ 修改管理员信息 ------------------
		acct.setRealName(arg0.getRealName());
		acctDao.update(acct);

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 update 】-【 COMPLETED 】");

	}

	@Override
	public void updatePass(final AdmAcctReq arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 updatePass 】-【 STARTED 】");

		// ------------------ 获取管理员详细信息 ------------------
		AdmAcct acct = queryByAcctLock(arg0.getAcct());
		if (null == acct) {
			throw StormrageTechException.instance(ErrCons.SERV_ERR, "管理员为空", StormrageTechException.ERR_APP,
					"【AdmAcctServImpl】- 【 UpdatePass 】");
		}
		acct.setSalt(SecureUtil.initUUID());
		acct.setPass(SecureUtil.initPass(arg0.getPass(), acct.getSign()));
		logger.debug(" 修改密码的原材料为 " + acct.toString());

		// ------------------ 修改用户密码 ------------------
		acctDao.updatePass(acct);

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 updatePass 】-【 COMPLETED 】");

	}

	@Override
	public void updateLocked(final Integer arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 updateLocked 】-【 STARTED 】");

		// ------------------ 获取管理员详细信息 ------------------
		AdmAcct acct = queryById(arg0);
		if (null == acct) {
			throw StormrageTechException.instance(ErrCons.SERV_ERR, "管理员为空", StormrageTechException.ERR_APP,
					"【AdmAcctServImpl】- 【 UpdatePass 】");
		}

		// ------------------ 修改用户锁定状态 ------------------
		Integer locked = acct.getLocked().equals(0) ? 1 : 0;
		acct.setLocked(locked);
		acctDao.updateLocked(acct);

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 updateLocked 】-【 COMPLETED 】");

	}

	@Override
	public void updateRole(final AdmAcctReq arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 updateRole 】-【 STARTED 】");

		// ------------------ 获取管理员详细信息 ------------------
		AdmAcct acct = queryById(arg0.getId());
		if (null == acct) {
			throw StormrageTechException.instance(ErrCons.SERV_ERR, "管理员为空", StormrageTechException.ERR_APP,
					"【AdmAcctServImpl】- 【 UpdatePass 】");
		}

		// ------------------ 修改用户权限 ------------------
		admAcctResServ.deleteByAcctId(arg0.getId());
		for (String resId : arg0.getRes().split(",")) {
			AdmAcctRes acctRes = AdmAcctRes.instance(arg0.getId(), Integer.valueOf(resId));
			admAcctResServ.create(acctRes);
		}

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 updateRole 】-【 COMPLETED 】");

	}

	@Override
	public AdmAcct queryById(final Integer arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryById 】-【 STARTED 】");

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", arg0);
		AdmAcct entity = acctDao.queryById(map);
		logger.debug(" - 查询结果为 -" + entity);

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryById 】-【 COMPLETED 】");
		return entity;

	}

	@Override
	public AdmAcct queryByAcct(final String arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryByAcct 】-【 STARTED 】");

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("acct", arg0);
		AdmAcct acct = acctDao.queryByAcct(map);
		logger.debug(" - 查询结构为 - " + acct);

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryByAcct 】-【 COMPLETED 】");
		return acct;

	}

	@Override
	public AdmAcct queryByAcctLock(final String arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryByAcctLock 】-【 STARTED 】");

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("acct", arg0);
		map.put("locked", 0);
		AdmAcct acct = acctDao.queryByAcctLock(map);
		logger.debug(" - 查询结构为 - " + acct);

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryByAcctLock 】-【 COMPLETED 】");
		return acct;

	}

	@Override
	public Set<String> queryPermSet() throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryPermSet 】-【 STARTED 】");

		Set<String> perms = new HashSet<String>();

		List<AdmRes> resList = resServ.queryList();
		for (AdmRes res : resList) {
			perms.add(res.getPermission());
		}

		logger.debug(" 用户权限列表为 " + perms.toString());

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryPermSet 】-【 COMPLETED 】");
		return perms;

	}

	@Override
	public Set<String> queryPermSetById(final Integer arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryPermSetById 】-【 STARTED 】");

		Set<String> perms = new HashSet<String>();

		List<AdmRes> resList = resServ.queryListByAcctId(arg0);
		for (AdmRes res : resList) {
			perms.add(res.getPermission());
		}

		logger.debug(" 用户权限列表为 " + perms.toString());

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryPermSetById 】-【 COMPLETED 】");
		return perms;

	}

	@Override
	public List<AdmRes> queryMenuById(final Integer arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryMenuById 】-【 STARTED 】");

		Set<String> perms = null;

		AdmAcct acct = queryById(arg0);

		if (acct.getRole().equals(0))
			perms = queryPermSet();
		if (acct.getRole().equals(1))
			perms = queryPermSetById(arg0);

		List<AdmRes> menus = new ArrayList<AdmRes>();

		List<AdmRes> resList = resServ.queryListByTypeParent("menu", 0);
		if (null != resList && resList.size() > 0) {
			for (AdmRes res : resList) {
				if (!hasPerm(perms, res))
					continue;
				List<AdmRes> children = resServ.queryListByTypeParent("menu", res.getId());
				if (null != children && children.size() > 0) {
					for (AdmRes child : children) {
						if (!hasPerm(perms, res)) {
							children.remove(child);
						}
					}
					res.setChildren(children);
				}
				menus.add(res);
			}
		}

		logger.debug(" 用户的menu为 " + menus.toString());

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryMenuById 】-【 COMPLETED 】");
		return menus;

	}

	@Override
	public List<AdmRes> queryRoleMenuById(final Integer arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryRoleMenuById 】-【 STARTED 】");

		Set<String> perms = null;

		AdmAcct acct = queryById(arg0);

		if (acct.getRole().equals(0))
			perms = queryPermSet();
		if (acct.getRole().equals(1))
			queryPermSetById(arg0);

		List<AdmRes> menus = new ArrayList<AdmRes>();

		List<AdmRes> resList = resServ.queryListByTypeParent("role", 1);
		for (AdmRes res : resList) {
			if (!hasPerm(perms, res))
				continue;
			menus.add(res);
		}

		logger.debug(" 用户的menu为 " + menus.toString());

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryRoleMenuById 】-【 COMPLETED 】");
		return menus;

	}

	@Override
	public AdmPermsRep queryPermsRep(final Integer arg0) throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryPermsRep 】-【 STARTED 】");

		AdmAcct acct = queryById(arg0);

		List<AdmResRep> array = resServ.queryList(arg0);

		List<AdmRes> list = resServ.queryListByAcctId(arg0);
		StringBuffer sb = new StringBuffer("");

		Iterator<AdmRes> it = list.iterator();
		while (it.hasNext()) {
			AdmRes res = it.next();
			sb.append(res.getId());
			sb.append(",");
		}
		String perms = sb.toString();
		perms = perms.substring(0, perms.length() - 1);

		AdmPermsRep rep = AdmPermsRep.instance(arg0, acct.getRole(), perms, array);

		logger.debug(" 用户权限列表为 " + perms.toString());

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryPermsRep 】-【 COMPLETED 】");
		return rep;

	}

	@Override
	public List<AdmAcctRep> queryList() throws StormrageTechException {

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryList 】-【 STARTED 】");

		List<AdmAcct> array = acctDao.queryList();
		int seq = 1;

		List<AdmAcctRep> list = new ArrayList<AdmAcctRep>();

		Iterator<AdmAcct> it = array.iterator();
		while (it.hasNext()) {
			AdmAcct acct = it.next();
			Integer count = resServ.queryCountByAcctId(acct.getId());
			AdmAcctRep rep = AdmAcctRep.instance(acct, seq, count);
			list.add(rep);
			seq++;
		}

		logger.debug(" 【 Serv 】- 【 AdmAcctServ 】- 【 queryList 】-【 COMPLETED 】");
		return list;

	}

	private Boolean isExist(String arg0) throws StormrageTechException {

		Boolean rs = Boolean.TRUE;

		AdmAcct entity = queryByAcct(arg0);
		if (null == entity)
			rs = Boolean.FALSE;

		return rs;

	}

	private boolean hasPerm(Set<String> permSet, AdmRes res) {

		if (null == permSet || StringUtils.isEmpty(res.getPermission())) {
			return false;
		}
		for (String permission : permSet) {
			WildcardPermission p1 = new WildcardPermission(permission);
			WildcardPermission p2 = new WildcardPermission(res.getPermission());
			if (p1.implies(p2) || p2.implies(p1)) {
				return true;
			}
		}
		return false;
	}

}
